import React from "react";
import "./styles.css";
import { run, useConcent, defWatch } from 'concent';

run({
    login: {
        state: {
            name: 'c2',
            addr: 'bj',
            info: {
                sex: '1',
                grade: '19',
            }
        },
        reducer: {
            selectSex(sex, moduleState) {
                const info = moduleState.info;
                info.sex = sex;
                return { info };
            }
        },
        computed: {
            funnyName(newState) {
                // 收集到funnyName对应的依赖是 name
                return `${newState.name}_${Date.now()}`
            },
            otherFunnyName(newState, oldState, fnCtx) {
                // 获取了funnyName的计算结果和newState.addr作为输入再次计算
                // 所以这里收集到otherFunnyName对应的依赖是 name addr
                return `${fnCtx.cuVal.funnyName}_${newState.addr}`
            }
        },
        watch: {
            // watchKey name和stateKey同名，默认监听name变化
            name(newState, oldState) {
                console.log(`name changed from ${newState.name} to ${oldState.name}`);
            },
            // 从newState 读取了addr， info两个属性的值，当前watch函数的依赖是 addr, info
            // 它们任意一个发生变化时，都会触发此watch函数
            addrOrInfoChanged: defWatch((newState, oldState, fnCtx) => {
                const { addr, info } = newState;
                if (fnCtx.isFirstCall) return;// 仅为了收集到依赖，不执行逻辑
                console.log(`addr is${addr}, info is${JSON.stringify(info)}`);
            }, { immediate: true })
        }
    }
})

function UI() {
    console.log('UI with state value');
    const { state, sync, dispatch } = useConcent('login');
    return (
        <div>
            name:<input value={state.name} onChange={sync('name')} />
            addr:<input value={state.addr} onChange={sync('addr')} />
            <br />
            info.sex:<input value={state.info.sex} onChange={sync('info.sex')} />
            info.grade:<input value={state.info.grade} onChange={sync('info.grade')} />
            <br />
            <select value={state.info.sex} onChange={(e) => dispatch('selectSex', e.target.value)}>
                <option value="male">male</option>
                <option value="female">female</option>
            </select>
        </div>
    );
}

function UI2() {
    console.log('UI2 with comptued value');
    const { state, moduleComputed, syncBool } = useConcent({ module: 'login', state: { show: true } });
    return (
        <div>
            {/* 当show为true的时候，当前组件的依赖是funnyName对应的依赖 name */}
            {state.show ? <span>dep is name: {moduleComputed.funnyName}</span> : 'UI2 no deps now'}
            <br /><button onClick={syncBool('show')}>toggle show</button>
        </div>
    );
}

function UI3() {
    console.log('UI3 with comptued value');
    const { state, moduleComputed, syncBool } = useConcent({ module: 'login', state: { show: true } });
    return (
        <div>
            {/* 当show为true的时候，当前组件的依赖是funnyName对应的依赖 name addr */}
            {state.show ? <span>dep is name,addr: {moduleComputed.otherFunnyName}</span> : 'UI3 no deps now'}
            <br /><button onClick={syncBool('show')}>toggle show</button>
        </div>
    );
}

export default function App() {
    return (
        <div className="App">
            <h3>try click toggle btn and open console to see render log</h3>
            <UI />
            <UI />
            <UI2 />
            <UI3 />
        </div>
    );
}
